Houdiniメモ : Solverで遊ぶ
Solverノードを使うと、現在フレームを加工した結果を次のフレームに反映させるような漸化式を扱うことができます。
例1. Boxを一定の速さで移動させる
Boxのx座標を毎フレーム0.1ずつ増やすような漸化式をSolverノードで実装してみます。
漸化式を使うと以下のように書けます。
$ X(F + 1) = X(F) + 0.1
$ X(F) : 第Fフレームのx座標
https://gyazo.com/ad55febacbf93a8974266c36df6a010a
■STEP 1 : ノード作成
BoxノードとSolverノードを作成し、以下のように接続します。
https://gyazo.com/97a491d9aabe4334f4fc7d4c2373b135
■STEP2 : Solverノードの実装
Solverノードの中に入ります。
以下のようなAttributeWrangleを作成し、Prev_Frameノードへ接続します。
code:VEX_1(c)
@P.x += 0.1;
https://gyazo.com/70581cfd395f749381078485379704a2
Solverノードの外へ戻り、再生するとBoxが毎フレーム0.1X方向へ移動するようになります。
https://gyazo.com/46d0a60775fd1860559b37e432e36a9f https://gyazo.com/ad55febacbf93a8974266c36df6a010a
■フレームレートに依存してしまう
今回の書き方では、フレームレート(FPS)が変わった時に移動スピードが変化してしまいます。
FPS24だと1秒ごとに2.4(= 0.1 * 24)移動しますが、FPS60だと1秒ごとに6.0(= 0.1 * 60)だけBoxがX方向へ移動します。
■フレームレートに依存させない形で書く
フレームレートに依存せずに秒速 0.1 でBoxを移動させたい場合、以下のように書きます。
code:VEX_2a(c)
@P.x += 0.1 / (float)$FPS;
■考え方
今回実装したSolverを漸化式で表すと以下のようになります。1フレーム経過するたびにx座標が0.1増加します。
$ X(F + 1) = X(F) + 0.1
$ X(F) : 第Fフレームにおけるx座標
$ X(F+1) : 1フレーム経過後のx座標
また、1秒経過すると x座標は 0.1 * フレーム数 だけ増加します。
$ X(F + N) = X(F) + 0.1 * N
$ N : フレームレート(1秒あたりのフレーム数秒)
$ X(F) : 現在時刻のX座標
$ X(F + N) : 1秒経過後のX座標
ここで$ 0.1 の代わりに $ 0.1 / N を使用すると、漸化式をフレームレートに依存しない形で表すことができます。
$ X(F + N) = X(F) + (0.1 / N) * N = X(F) + 0.1
$ X(F + N) = X(F) + 0.1
フレーム間の漸化式は以下のようになります。
$ X(F + 1) = X(F) + \frac{0.1}{N}
code:VEX_2b(c)
@P.x += 0.1 / (float)$FPS;
例2. Boxを一定の速さで大きくする
今回は1フレームごとにBoxを1.1倍にしてみます。
https://gyazo.com/9133567421301251890d28f0754fdaca
■AttributeWrangleの書き換え
Solver内部のAttributeWrangleコードを以下のように書き換えることで、Boxの大きさが1フレームごとに1.1倍になります。
code:VEX_3(c)
@P *= 1.1;
https://gyazo.com/8139291c5e3b0e5a7dd873333e8f9ee1
■フレームレートに依存させない
フレームレートに依存せずにBoxの大きさを毎秒 1.1倍 にしたい場合、以下のように書きます。
code:VEX_4a(c)
@P *= pow(1.1, 1 / (float)$FPS);
■考え方
今回実装したSolverを漸化式で表すと以下のようになります。1フレーム経過するたびにポイント座標が1.1倍になっています。
$ P(F + 1) = 1.1 \cdot P(F)
$ P(F) : 第Fフレームにおけるポイント座標
$ P(F+1) : 1フレーム経過後のポイント座標
1秒経過すると ポイント座標は $ 1.1 ^ N 倍になります。 (1秒経過するとフレーム数はN増加します)
$ P(F + N) = {1.1}^N \cdot P(F)
$ N : フレームレート(1秒あたりのフレーム数秒)
$ P(F) : 第Fフレームにおけるポイント座標
$ P(F + N) : 1秒経過後のポイント座標
ここで、$ 1.1 の代わりに $ 1.1^{1/N} を使用すると、漸化式をフレームレートに依存しない形で表すことができます。
$ P(F + N) = {(1.1^{1/N})}^N \cdot P(F) = 1.1 \cdot P(F)
$ P(F + N) = 1.1 \cdot P(F)
$ P(F) : 第Fフレームにおけるポイント座標
$ P(F + N) : 1秒経過後のポイント座標
フレーム間の漸化式は以下のようになります。
$ P(F + 1) = 1.1^{1/N} \cdot P(F)
上記の漸化式をVEXで書くと以下のようになります。
code:VEX_4b(c)
@P *= pow(1.1, 1 / (float)$FPS);